package com.chushouya.controller.manager.admin;


import com.chushouya.manager.dto.admin.user.UserOnline;
import com.chushouya.manager.service.admin.AdminLoginService;
import com.general.framework.core.constant.Constants;
import com.general.framework.core.enums.BusinessType;
import com.general.framework.core.enums.ContextUserType;
import com.general.framework.core.lang.Dates;
import com.general.framework.core.lang.Strings;
import com.general.framework.core.schema.PageResult;
import com.general.framework.core.schema.Response;
import com.general.framework.data.redis.RedisCache;
import com.general.framework.web.annotations.Log;
import com.chushouya.manager.dto.admin.login.LoginUser;
import com.chushouya.manager.dto.admin.server.Server;
import com.chushouya.common.constant.ServiceType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;

@Api(tags = ServiceType.PLATFORM + "监控中心")
@RestController
@RequestMapping(ServiceType.PLATFORM + "/monitor/")
@Slf4j
public class MonitorController {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private AdminLoginService adminLoginService;

    @Resource
    private RedisCache redisCache;

    @ApiOperation("缓存监控")
    @GetMapping("cache")
    public Response<Map> cache() {
        Map<String, Object> result = new HashMap<>(3);
        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
        result.put("info", info);

        Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
        Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
        result.put("dbSize", dbSize);

        List<Map<String, String>> pieList = new ArrayList<>();
        commandStats.stringPropertyNames().forEach(key -> {
            Map<String, String> data = new HashMap<>(2);
            String property = commandStats.getProperty(key);
            data.put("name", Strings.removeStart(key, "cmdstat_"));
            data.put("value", Strings.substringBetween(property, "calls=", ",usec"));
            pieList.add(data);
        });
        result.put("commandStats", pieList);
        return Response.success(result);
    }
    @ApiOperation("服务器监控")
    @GetMapping("/server")
    public Response<Server> getInfo() {
        try {
            Server server = new Server();
            server.copyTo();
            return Response.success(server);
        } catch (Exception e) {
            log.error("获取服务器监控信息异常", e);
            return Response.error("获取服务器监控信息异常");
        }
    }


    @ApiOperation("在线用户监控")
    @GetMapping("/onlineUser")
    public Response<PageResult<UserOnline>> onlineUser(String ipAddr, String userName) {
        Collection<String> keys = redisCache.keys(Constants.ADMIN_LOGIN_TOKEN_KEY.concat("*"));
        List<UserOnline> userOnlineList = new ArrayList<>();
        for (String key : keys) {
            LoginUser user = redisCache.getCacheObject(key);
            if (Strings.isNotEmpty(ipAddr) && Strings.isNotEmpty(userName)) {
                if (Strings.contains(user.getIpAddr(), ipAddr) && Strings.contains(user.getUserName(), userName )) {
                    userOnlineList.add(this.loginUserToUserOnline(user));
                }
            } else if (Strings.isNotEmpty(ipAddr)) {
                if (Strings.contains(user.getIpAddr(), ipAddr)) {
                    userOnlineList.add(this.loginUserToUserOnline(user));
                }
            } else if (Strings.isNotEmpty(userName)) {
                if (Strings.contains(user.getUserName(), userName )) {
                    userOnlineList.add(this.loginUserToUserOnline(user));
                }
            } else {
                userOnlineList.add(this.loginUserToUserOnline(user));
            }
        }
        userOnlineList.sort(Comparator.comparing(UserOnline::getLoginTime).reversed());
        return Response.success(PageResult.of(userOnlineList));
    }

    private UserOnline loginUserToUserOnline(LoginUser user) {
        UserOnline userOnline = new UserOnline();
        userOnline.setTokenId(user.getJwtToken());
        userOnline.setUserName(user.getUserName());
        userOnline.setUserType(ContextUserType.getDesc(user.getUserType()));
        userOnline.setIpAddr(user.getIpAddr());
        userOnline.setLoginLocation(user.getLoginLocation());
        userOnline.setBrowser(user.getBrowser());
        userOnline.setOs(user.getOs());
        userOnline.setLoginTime(Dates.parseDate(user.getLoginTime()));
        userOnline.setExpireTime(Dates.parseDate(user.getExpireTime()));
        return userOnline;
    }

    @ApiOperation("强退用户")
    @Log(businessType = BusinessType.DELETE)
    @PostMapping("/forceLogout")
    public Response<Void> forceLogout(String tokenId) {
        adminLoginService.logout(tokenId);
        return Response.success();
    }

}
